#include "Defense.h"
#include <vector>
#include <complex>
#include <iostream>
#include "RatingConvert.h"
using namespace std;

enum Stats{
PRIMARY = 0,
SECONDARY = 1,
CRIT = 2,
SURGE = 3,
ALACRITY =4,
POWER = 5,
ACCURACY = 6,
DEFENSE = 7,
SHIELD = 8,
ABSORB = 9,
ARMOR = 10,
GEN_SHIELD = 11,
GEN_ABSORB = 12,
LEVEL = 13,
MAIN_HAND = 14,
OFF_HAND = 15};
vector <double> Vanguard(const vector <double>& stats) {
    double base_DR = 9;
    double base_armor_mult = 1.775;
    double base_def_per = 5;
    double base_shld_per = 32;
    double base_abs_per = 26;

    vector <double> mitigations(5, 0);
    mitigations = Mitigation(base_DR, base_armor_mult, base_abs_per, base_shld_per, base_def_per, stats);

    return mitigations;
}

vector <double> Shadow(const vector <double>& stats) {
    double base_DR = 2;
    double base_armor_mult = 2.758;
    double base_def_per = 16;
    double base_shld_per = 35;
    double base_abs_per = 24;

    vector <double> mitigations(5, 0);
    mitigations = Mitigation(base_DR, base_armor_mult, base_abs_per, base_shld_per, base_def_per, stats);

    return mitigations;
}

vector <double> Guardian(const vector <double>& stats) {
    double base_DR = 6;
    double base_armor_mult = 1.615;
    double base_def_per = 17;
    double base_shld_per = 24;
    double base_abs_per = 20;

    vector <double> mitigations(5, 0);
    mitigations = Mitigation(base_DR, base_armor_mult, base_abs_per, base_shld_per, base_def_per, stats);

    return mitigations;
}


double MitigationCalc(double attAcc, double attCrit, double attSurge, double defense, double armorDR, double shield, double absorb) {
    double mitigation = 100*(1 - ((min(attAcc - defense, 1.0)) * (1 - armorDR / 100)*(attCrit * (1 + attSurge) + min(shield, 1 - attCrit)*(1 - absorb) + max(1 - shield - attCrit, 0.0))));
    return mitigation;
}

vector <double> Mitigation(double base_DR, double base_armor_mult,
        double base_abs_per, double base_shld_per, double base_def_per,
        const vector <double>& stats) {

    double level = stats[LEVEL];
    double armor = stats[ARMOR];
    double defRat = stats[DEFENSE];
    double shldRat = stats[SHIELD];
    double absRat = stats[ABSORB];
    double genShldChance = 0;
    double genAbsPercent = 0;

    //assuming these are constant since I've yet to see one differ

    
    //assuming level 50 attackers for now
    int attLevel = 50;
//    cout << "Enter the level of your attacker (bosses are 52):\t";
//    cin >> attLevel;
//    cout << endl;
    //assumptions about attacker
    double attCrit = 0.1;
    double attSurge = 0.5;
    double attAcc = 1 + 0.05 * (attLevel - level);

    double defense, armorDR, shield, absorb, mitigation;
    vector <double> mitigations(5, 0);
    for (int n = 0; n < 5; n++) {
        switch (n) {
            case 0: //current mitigation
                armorDR = Armor(level, base_DR, armor);
                defense = Defense(level, base_def_per, defRat);
                shield = Shield(level, base_shld_per, shldRat, genShldChance);
                absorb = Absorb(level, base_abs_per, absRat, genAbsPercent);
                mitigation = MitigationCalc(attAcc, attCrit, attSurge, defense, armorDR, shield, absorb);
                break;
            case 1:
                armor = stats[ARMOR] + 100 * base_armor_mult;
                armorDR = Armor(level, base_DR, armor);
                defense = Defense(level, base_def_per, defRat);
                shield = Shield(level, base_shld_per, shldRat, genShldChance);
                absorb = Absorb(level, base_abs_per, absRat, genAbsPercent);
                mitigation = MitigationCalc(attAcc, attCrit, attSurge, defense, armorDR, shield, absorb);
                armor = stats[ARMOR];
                break;
            case 2:
                defRat = stats[DEFENSE] + 1;
                armorDR = Armor(level, base_DR, armor);
                defense = Defense(level, base_def_per, defRat);
                shield = Shield(level, base_shld_per, shldRat, genShldChance);
                absorb = Absorb(level, base_abs_per, absRat, genAbsPercent);
                mitigation = MitigationCalc(attAcc, attCrit, attSurge, defense, armorDR, shield, absorb);
                defRat = stats[DEFENSE];

                break;
            case 3:
                shldRat = stats[SHIELD] + 1;
                armorDR = Armor(level, base_DR, armor);
                defense = Defense(level, base_def_per, defRat);
                shield = Shield(level, base_shld_per, shldRat, genShldChance);
                absorb = Absorb(level, base_abs_per, absRat, genAbsPercent);
                mitigation = MitigationCalc(attAcc, attCrit, attSurge, defense, armorDR, shield, absorb);
                shldRat = stats[SHIELD];
                break;
            case 4:
                absRat = stats[ABSORB] + 1;
                armorDR = Armor(level, base_DR, armor);
                defense = Defense(level, base_def_per, defRat);
                shield = Shield(level, base_shld_per, shldRat, genShldChance);
                absorb = Absorb(level, base_abs_per, absRat, genAbsPercent);
                mitigation = MitigationCalc(attAcc, attCrit, attSurge, defense, armorDR, shield, absorb);
                absRat = stats[ABSORB];
                break;
        }
        mitigations[n] = mitigation;
    }
    return mitigations;
}
